<?php

namespace app\admin\controller;
//验证类
use app\admin\controller\Auth;
use think\Request;

use function PHPSTORM_META\type;

class Install extends Auth
{

    //需验证方法集
    protected $is_check_login = ['*'];

    // 扩展安装入口
    public function init()
    {
        // 当前请求域名
        $domain = $_SERVER['HTTP_HOST'];
        // 判断变量是否定义
        if ($this->isDefine(['id', 'type'])) {
            $post = input('post.');
            // 安装
            if ($post['type'] == 'install') {
                return $this->install();
            }
            // 卸载
            if ($post['type'] == 'uninstall') {
                return $this->uninstall();
            }
        }
    }

    // 远程公告
    public function notice()
    {
        try {
            $data = file_get_contents(CMS_MOTICE_URL);
            return json_decode($data, true);
        } catch (\Exception $th) {
            return '';
        }
    }

    // 删除安装包
    public  function unfile($filedir, $p = false)
    {
        if ($p) {
            $path =  $filedir;
        } else {
            // 文件路径
            $path = CMS_UPDATE_PATH . $filedir;
        }

        // 删除文件夹内文件
        $deldir = function ($pt) use (&$deldir) {
            //先删除目录下的文件：
            $dh = opendir($pt);
            while ($file = readdir($dh)) {
                if ($file != "." && $file != "..") {
                    $fullpath = $pt . "/" . $file;
                    if (!is_dir($fullpath)) {
                        unlink($fullpath);
                    } else {
                        $deldir($fullpath);
                    }
                }
            }
            closedir($dh);
            @rmdir($pt);
        };
        // 删除文件
        $deldir($path);
        //删除当前文件夹：
        if (@rmdir($path)) {
            return true;
        } else {
            return false;
        }
    }

    // 安装
    public function install()
    {
        // 验证
        $auth = config('requser_auth');
        // 获取商品信息
        $code = @file_get_contents(CMS_MILL_URL . "&type=" . input('post.type') . "&id=" . input('post.id') . "&auth=" . $auth);
        // 解析数据
        $code = json_decode($code, true);
        // 判断获取详情
        if (isset($code['code'])) {
            // if ($code['good']) {
            //     return $this->unfile(CMS_PATH, true);
            // } else {
            //     return $this->downSoftware($code['data']['download'], $code['data']);
            // }
            return $this->downSoftware($code['data']['download'], $code['data']);
        } else {
            $data = ['code' => 500, 'msg' => "与远程服务端断开连接"];
            return json_encode($data);
        }
    }

    // 卸载
    public function uninstall()
    {
        // 验证
        $auth = config('requser_auth');
        // 获取商品信息
        $code = @file_get_contents(CMS_MILL_URL . "&id=" . input('post.id') . "&auth=" . $auth);
        // 解析数据
        $code = json_decode($code, true);
        // 判断获取详情
        if (isset($code['code'])) {
            return $this->delExtend($code['data']);
        } else {
            $data = ['code' => 500, 'msg' => "与远程服务端断开连接"];
            return json_encode($data);
        }
    }

    // 移除扩展
    public function delExtend($code = [])
    {
        // 判断类型
        if ($code['type'] == "1") {
            // 移除模板文件
            $tmp = CMS_PATH . $code['un_template'];
            if (is_dir($tmp)) {
                $this->unfile($tmp, true);
            }
            // 移除模板静态文件
            $sta = CMS_PATH . $code['un_static'];
            if (is_dir($sta)) {
                // 移除模板文件
                $this->unfile($sta, true);
            }
            // 检测卸载残留
            if (is_dir($tmp) && is_dir($sta)) {
                $data = ['code' => 500, 'msg' => "卸载失败,请重试或者手动删除"];
                return json_encode($data);
            } else {
                $this->InstallationRecord('un');
                $data = ['code' => 200, 'msg' => "卸载完成"];
                return json_encode($data);
            }
        } else if ($code['type'] == "2") {
            // 移除插件文件
            $plug = CMS_PATH . $code['un_plug'];
            if (is_dir($plug)) {
                $this->unfile($plug, true);
            }
            // 检测卸载残留
            if (is_dir($plug)) {
                $data = ['code' => 500, 'msg' => "卸载失败,请重试或者手动删除"];
                return json_encode($data);
            } else {
                $this->InstallationRecord('un');
                $data = ['code' => 200, 'msg' => "卸载完成"];
                return json_encode($data);
            }
        }
    }

    // 软件下载器
    public function downSoftware($url, $code = [], $filename = CMS_UPDATE_PATH)
    {
        // 地址不为空
        if (trim($url) == '') {
            $data = ['code' => 500, 'msg' => "下载资源不存在"];
            return json_encode($data);
        }

        $time = time();
        $path = $filename . $time;

        //创建保存目录
        if (!file_exists($path) && !mkdir($path, 0777, true)) {
            $data = ['code' => 500, 'msg' => "安装失败,无安装权限"];
            return json_encode($data);
        }

        // 获取文件后缀
        $_ext = strrchr($url, '.');

        $user_agent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"; //UA
        $ch = curl_init(); //启动会话
        curl_setopt($ch, CURLOPT_URL, $url); //访问地址
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //支持重定向
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //参数为1表示传输数据，为0表示直接输出显示
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // 从证书中检查SSL加密算法是否存在
        curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);   // 伪造ua
        curl_setopt($ch, CURLOPT_TIMEOUT, 120); //设置curl允许执行的最长秒数
        $content = (curl_exec($ch)); //移除两边空白或其他字符
        curl_close($ch); //关闭会话

        // 保存路径
        $destination = $path . '/' . $time . $_ext;
        $file = fopen($destination, "w+");
        fputs($file, $content); //写入文件
        fclose($file); //关闭文件

        // 安装包解压
        if ($this->releaseFile($destination, $path)) {
            // 判断安装类型 1.模板 2.插件 3.其他
            if ($code['type'] == '1') {
                // 模板文件解压
                $template = $path . "/template.zip";
                if (!$this->releaseFile($template, CMS_PATH . $code['template'])) {
                    $data = ['code' => 500, 'msg' => "安装失败,模板文件释放失败!"];
                    return json_encode($data);
                }

                // 模板静态文件解压
                $static = $path . "/static.zip";
                if (!$this->releaseFile($static, CMS_PATH . $code['static'])) {
                    $data = ['code' => 500, 'msg' => "安装失败,模板文件释放失败!"];
                    return json_encode($data);
                }
            }

            if ($code['type'] == '2') {
                // 插件文件解压
                $plug = $path . "/plug.zip";
                if (!$this->releaseFile($plug, CMS_PATH . $code['plug'])) {
                    $data = ['code' => 500, 'msg' => "安装失败,插件文件释放失败!"];
                    return json_encode($data);
                }
            }

            // 移除安装包
            $this->unfile($time);
            $data = ['code' => 200, 'msg' => "安装成功"];
            // 记录安装记录
            $this->InstallationRecord();
            return json_encode($data);
        } else {
            $data = ['code' => 500, 'msg' => "安装失败,文件释放失败!"];
            return json_encode($data);
        }
    }

    // 安装记录
    public function InstallationRecord($type = 'add')
    {
        // 获取数据
        $data = getConfig('install')['install'];
        // 转数组
        $data = explode(",", $data);
        // 数据初始化
        $data = $data == null ? [] : $data;
        // 安装
        if ($type == 'add') {
            // 转字符串
            $info['install'] = implode(',', $data) . "," . input('post.id');
        } else { //卸载
            $dat = [];
            $i = 0;
            foreach ($data as $key => $value) {
                if ($value != input('post.id')) {
                    $dat[$i] = $value;
                    $i++;
                }
            }
            // 转字符串
            $info['install'] = implode(',', $dat);
        }
        // 保存
        $res = setConfigAll('install', $info);
        //返回处理结果
        if ($res) {
            return true;
        } else {
            return false;
        }
    }

    // 释放文件
    public function releaseFile($file, $path)
    {
        // 实例化压缩文件类
        $zip = new \ZipArchive;
        if ($zip->open($file) === TRUE) {
            //中文文件名要使用ANSI编码的文件格式
            $zip->extractTo($path); //提取全部文件
            // 关闭操作
            $zip->close();
            return true;
        } else {
            return false;
        }
    }
}
